package com.zhou.util;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.quartz.TriggerUtils;
import org.quartz.impl.triggers.CronTriggerImpl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 基于joda-time的工具方法
 * 参考资料 
 * http://blog.csdn.net/dhdhdh0920/article/details/7415359
 * http://persevere.iteye.com/blog/1755237
 * timezone 资料http://joda-time.sourceforge.net/timezones.html
 * @author admin
 *
 */

public final class TimeUtils {

//	public static final DateTimeZone tz =DateTimeZone.forTimeZone(TimeZone.getTimeZone(GameConfig.TIME_ZONE));//设置时区为利雅得时间
  	public static  final long SECOND = 1000l;
	public static  final long MINUTE = 60 * SECOND;
	public static  final long HOUR = 60 * MINUTE;
	public static  final long DAY = 24 * HOUR;
	
	private static final DateTimeFormatter FORMAT_MONTH= DateTimeFormat.forPattern("yyyyMM");//自定义日期格式
	private static final DateTimeFormatter FORMAT_YEAR= DateTimeFormat.forPattern("yyyy");//自定义日期格式
	private static final DateTimeFormatter FORMAT_DAY= DateTimeFormat.forPattern("yyyy-MM-dd");//自定义日期格式
	private static final DateTimeFormatter FORMAT_CH_DATE_TIME = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
	private static final DateTimeFormatter FORMAT_CH_DATE_HOUR = DateTimeFormat.forPattern("yyyy-MM-dd HH");
	private static final DateTimeFormatter FORMAT_NO_SPR = DateTimeFormat.forPattern("yyyyMMddHHmmss");
	private static final DateTimeFormatter FORMAT_DAY_NO_SPR = DateTimeFormat.forPattern("yyyyMMdd");
	
	public static String formatDate(DateTime dt){
		return dt.toString(FORMAT_DAY);
	}
	
	public static String formatDayHour(DateTime dt){
		return dt.toString(FORMAT_CH_DATE_HOUR);
	}


	public static String formatNoSpr(DateTime dt){
		return dt.toString(FORMAT_NO_SPR);
	}
	public static String formatDateNoSpr(DateTime dt){
		return dt.toString(FORMAT_DAY_NO_SPR);
	}

	public static String formatNoSpr(long time){
		return getTime(time).toString(FORMAT_NO_SPR);
	}
	
	public static String formatDate(long time){
		return formatDate(getTime(time));
	}

	public static String formatChDateTime(DateTime dt){
		return dt.toString(FORMAT_CH_DATE_TIME);
	}
	
	public static String formatChDateTime(long time){
		return formatChDateTime(getTime(time));
	}
	
	public static String formatYear(long time){
		return formatYear(getTime(time));
	}
	
	public static String formatYear(DateTime dt){
		return dt.toString(FORMAT_YEAR);
	}
	

	
	/**
	 * 是否同一周
	 * @param time1
	 * @param time2
	 * @return
	 */
	public static boolean isSameWeek(long time1, long time2) {
		DateTime d1 = TimeUtils.getTime(time1);
		DateTime d2 = TimeUtils.getTime(time2);
		if (d1.getYear() != d2.getYear()) return false;
		if (d1.getWeekOfWeekyear() != d2.getWeekOfWeekyear()) return false;
		return true;//同一年且同一周
	}
	
	/**
	 * 检测是否是同一天

	 * @return
	 */
	public static boolean isSameDay(long start,long end){
		DateTime startDate = TimeUtils.getTime(start);
		DateTime endDate = TimeUtils.getTime(end);
		return isSameDay(startDate,endDate);
	}

	
	
	/***
	 * 检测是否是同一天
	 * @param time1
	 * @param time2
	 * @return
	 */
	public static boolean isSameDay(DateTime time1 , DateTime time2){
		String d1= formatDate(time1);
		String d2= formatDate(time2);
		if(d1.equals(d2)){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 检测是否是同一天
	 * @param time
	 * @return
	 */
	public static boolean isSameTodayDay(long time){
		return isSameDay(now().getMillis(),time);
	}
	
	/**
	 * 检测是否是同一天
	 * @return
	 */
	public static boolean isSameHour(long start,long end){
		DateTime startDate = TimeUtils.getTime(start);
		DateTime endDate = TimeUtils.getTime(end);
		return isSameHour(startDate,endDate);
	}

	
	
	/***
	 * 检测是否是同一天
	 * @param time1
	 * @param time2
	 * @return
	 */
	public static boolean isSameHour(DateTime time1 , DateTime time2){
		String d1= formatDayHour(time1);
		String d2= formatDayHour(time2);
		if(d1.equals(d2)){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 获得每周周几
	 * @return
	 */
	public static int getWeek(){
		return now().getDayOfWeek();
	}
	
	/**
	 *  检测两个时间之间相差几天
	 * @param start
	 * @param end
	 * @return
	 * boolean
	 */
	public static int getBetweenDay(long start, long end) {
		DateTime startDate = TimeUtils.getTime(start);
		DateTime endDate = TimeUtils.getTime(end);
		return getBetweenDay(startDate, endDate);
	}
	public static int getBetweenDay(DateTime startDate, DateTime endDate) {
		String d1 = formatDate(startDate);
		String d2 = formatDate(endDate);
		long start1 = parseChDayTime(d1+" 00:00:00").getMillis();
		long start2 = parseChDayTime(d2+" 00:00:00").getMillis();

		int day =(int) ((start2-start1)/DAY);
		return Math.abs(day);
	}
	
	/**
	 * 根据long获得时间
	 * @param time
	 * @return
	 */
	public static DateTime getTime(long time){
		return new DateTime(time);
	}
	
	/**
	 * 根据字符串获得时间
	 * @param str
	 * @return
	 */
	public static DateTime parseDay(String str){
		return  DateTime.parse(str,FORMAT_DAY);
	}



	/**
	 * 根据字符串获得时间
	 * @param str
	 * @return
	 */
	public static DateTime parseChDayTime(String str){
		return  DateTime.parse(str, FORMAT_CH_DATE_TIME);
	}




	/**
	 * 获得当前时间
	 * @return
	 */
	public static String nowStr(){
		return formatChDateTime(nowLong());
	}
	
	/**
	 * 获得当前时间
	 * @return
	 */
	public static DateTime now(){
		return DateTime.now();
	}
	
	/**
	 * 获得当前时间
	 * @return
	 */
	public static long nowLong(){
	
		return now().getMillis();
	}
	
	public static void main(String[] args) {
//		System.out.println(chDate(1512333741000L));
//		System.out.println(chDate(1563067928000l));
//		System.out.println(chDate(1563067838000l));
//		System.out.println(chDate(1563067958000l));
//		System.out.println(chDate(1563067931000l));
//		System.out.println(chDate(1562649768000l + 86400000));
//		System.out.println(GameConfig.GARR_ERR_IDS.indexOf("8,") > -1);
//		
//		DateTime time = now();
//		time = time.plusHours(-time.getHourOfDay());
//		time = time.plusMinutes(-time.getMinuteOfHour());
//		time = time.plusSeconds(-time.getSecondOfMinute());
//		time = time.plusMillis(time.getMillisOfSecond());
//		System.out.println(time.getMillis()+" : " + time.toString() +" : " + formatAdjust(time));
//		System.out.println(getToday0Time());
//		System.out.println(formatSimpleDateHour(now()));
//		System.out.println("123,456,".indexOf("456,"));
		System.out.println(TimeUtils.now());
		System.out.println(TimeUtils.now().plusSeconds(86400));
		System.out.println(TimeUtils.now().plusSeconds(86400*2));
		
	}
	
	public static int nowInteger(){
		return (int)(now().getMillis()/SECOND);
	}

	

	/**
	 * 将字符串时间转化为long
	 * @param time
	 * @return
	 */
	public static long parseChDayTimeNotNull(String time){
		if(time == null || time.isEmpty()){
			return 0;
		}
		return parseChDayTime(time).getMillis();
	}
	
    /**
	 * 得到今天24点
	 * @return
	 */
	public static long getToday24Time(){
		Calendar c = Calendar.getInstance();
		c.set(Calendar.DATE, c.get( Calendar.DATE ));
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND,0);
        return c.getTimeInMillis() + 1* SECOND;
	}
	  /**
		 * 得到今天0点
		 * @return
		 */
	public static long getToday0Time(){

        return getDay0Time(now());
	}
	/**
	 *
	 * @param time
	 * @return
	 */
	public static long getDay0Time(DateTime time){
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(time.getMillis());
		c.set(Calendar.DATE, c.get( Calendar.DATE ));
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND,0);
		return c.getTimeInMillis();
	}
	/**
	 * 获得指定时间的上一个整小时时间<br>
	 * 如2019-09-11 08:33:32 返回 2019-09-11 08:00:00
	 * @param time
	 * @return
	 */
	public static long getFloorHourTime(long time) {
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(time);
		c.set(Calendar.DATE, c.get(Calendar.DATE));
        c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY));
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND,0);
        return c.getTimeInMillis();
	}


	
	/**
	 * 获得当前时间的上一个整小时时间<br>
	 * 如2019-09-11 08:33:32 返回 2019-09-11 08:00:00

	 * @return
	 */
	public static long getFloorHourTime() {
		return getFloorHourTime(TimeUtils.nowLong());
	}
	

	
	/**
	 * 判断当前时间是否在两个时间段内
	 * @return
	 */
	public static boolean timeIsBetween(String start, String end) {
		long startTime = parseChDayTime(start).getMillis();
		long endTime = parseChDayTime(end).getMillis();
		long now = nowLong();
		if (now >= startTime && now <= endTime) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 返回昨天的日期 2016-07-03
	 * @return
	 */
	public static String formatYesterday() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1);
		String yesterday = new SimpleDateFormat("yyyy-MM-dd ").format(cal
				.getTime());
		return yesterday;
	}
	
	/**
	 * 获取最近的cron表达式的执行时间
	 * @param cron 表达式
	 * @param calendarField 日期计量单位
	 * @param num 日期（如1个月内）
	 * @return
	 */
	public static List<Date> getCronNextTime(String cron, int calendarField, int num) throws Exception {

		try {

			CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();

			// 每天早上10：15触发
			cronTriggerImpl.setCronExpression(cron);

			Calendar calendar = Calendar.getInstance();
			Date now = calendar.getTime();
			calendar.add(calendarField, num);// 统计的区间段设置

			// 这里的时间是根据corn表达式算出来的值
			List<Date> dates = new ArrayList<>(TriggerUtils.computeFireTimesBetween(cronTriggerImpl, null, now, calendar.getTime()));

			return dates;

		} catch (ParseException e) {
			throw new Exception("获取cron执行日期时出错!");
		}

	}

    public static boolean isTimeout(long sourceTime) {
		return isTimeout(sourceTime, TimeUtils.nowLong());
    }

	/**
	 * 是否超时，如果 sourceTime <= targeTime 表示超时
	 * @param sourceTime 判断时间
	 * @param targeTime 目标时间
	 * @return
	 */
	public static boolean isTimeout(long sourceTime,long targeTime) {
		return sourceTime <= targeTime;
	}


	public static String formatYearWeek(DateTime time) {
		int yearweek = time.getWeekOfWeekyear();
		StringBuilder sb = new StringBuilder();
		sb.append(time.getYear());
		if (yearweek < 10)sb.append("0");
		sb.append(yearweek);
		return sb.toString();
	}
	public static String formatYearMonth(DateTime time) {
		int month = time.getMonthOfYear();
		StringBuilder sb = new StringBuilder();
		sb.append(time.getYear());
		if (month < 10)sb.append("0");
		sb.append(month);
		return sb.toString();
	}


	public static DateTime getWeekMonday0Time(DateTime time){
		return
				time.withDayOfWeek(2).withHourOfDay(0).withMinuteOfHour(0)
						.withSecondOfMinute(0).withMillisOfSecond(0);
	}

	public static DateTime getMonth1D0Time(DateTime time){
		return
				time.withDayOfMonth(1).withHourOfDay(0).withMinuteOfHour(0)
						.withSecondOfMinute(0).withMillisOfSecond(0);
	}
	public static DateTime getYear1D0Time(DateTime time){
		return
				time.withDayOfYear(1).withHourOfDay(0).withMinuteOfHour(0)
						.withSecondOfMinute(0).withMillisOfSecond(0);
	}
}
